package com.vteba.utils.common;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Word 2007的工具类
 * @author yinlei
 * @date 2015年9月7日 下午2:33:02
 */
public class WordUtils {
	private static final Logger LOGGER = LoggerFactory.getLogger(WordUtils.class);

	/**
	 * 在docx文件中插入图片
	 * @param docxFis docx文件路径
	 * @param images 图片文件数组，文件是全路径
	 * @return XWPFDocument，docx文件 
	 */
	public static XWPFDocument update(String docx, String[] images) {
		XWPFDocument document = createDocument(docx);
		update(document, images);
		return document;
	}

	/**
	 * 在docx文件中插入图片
	 * @param docxFis docx文件路径
	 * @param images 图片文件数组，文件是全路径
	 * @param fos 修改后的word docx文件流 
	 */
	public static void update(String docx, String[] images, FileOutputStream fos) {
		XWPFDocument document = createDocument(docx);
		update(document, images);
		try {
			document.write(fos);
		} catch (IOException e) {
			LOGGER.error("Copy document, IO Exception，msg=[{}].", e.getMessage());
		}
	}
	
	/**
	 * 在docx文件中插入图片
	 * @param docxFis docx文件流
	 * @param images 图片文件数组，文件是全路径
	 * @param fos 修改后的word docx文件流
	 */
	public static void update(FileInputStream docxFis, String[] images, FileOutputStream fos) {
		XWPFDocument document = createDocument(docxFis);
        update(document, images);
		try {
			document.write(fos);
		} catch (IOException e) {
			LOGGER.error("Copy document, IO Exception，msg=[{}].", e.getMessage());
		}
	}

	/**
	 * 在docx文件中插入图片
	 * @param document docx文件
	 * @param images 图片文件数组，文件是全路径
	 */
	public static void update(XWPFDocument document, String[] images) {
        XWPFParagraph paragraph = document.createParagraph(); // 创建段落
        XWPFRun run = paragraph.createRun(); // 在段落中添加片段
        
        for (String image : images) {
        	int format = fileFormat(image);
        	try {
        		// run.setText(image); // 添加文字
        		// run.addBreak(); // 换行
				run.addPicture(new FileInputStream(image), format, image, Units.toEMU(150), Units.toEMU(150));
			} catch (InvalidFormatException e) {
				LOGGER.error("Invalid File Format, msg=[{}].", e.getMessage());
			} catch (IOException e) {
				LOGGER.error("Add run image, IO Exception，msg=[{}].", e.getMessage());
			}
        }
	}
	
	/**
	 * 创建docx文件
	 * @param docxFis docx文件流
	 * @return XWPFDocument
	 */
	private static XWPFDocument createDocument(FileInputStream docxFis) {
		XWPFDocument doc = null;
		try {
			doc = new XWPFDocument(docxFis);
		} catch (IOException e) {
			LOGGER.error("IO Exception，msg=[{}].", e.getMessage());
			throw new RuntimeException("create XWPFDocument, IO Exception.", e);
		}
		return doc;
	}
	
	/**
	 * 创建docx文件
	 * @param docxFis docx文件路径
	 * @return XWPFDocument
	 */
	private static XWPFDocument createDocument(String docxPath) {
		XWPFDocument doc = null;
		try {
			FileInputStream fis = new FileInputStream(docxPath);
			doc = new XWPFDocument(fis);
		} catch (IOException e) {
			LOGGER.error("IO Exception，msg=[{}].", e.getMessage());
			throw new RuntimeException("create XWPFDocument, IO Exception.", e);
		}
		return doc;
	}
	
	/**
	 * 匹配文件类型
	 * @param fileName 文件名
	 * @return 对应的图片常量
	 */
	private static int fileFormat(String fileName) {
		int format;
		if (fileName == null) {
			return -1000;
		}
		fileName = fileName.toLowerCase();
		if (fileName.endsWith(".emf")) {
			format = XWPFDocument.PICTURE_TYPE_EMF;
		} else if (fileName.endsWith(".wmf")) {
			format = XWPFDocument.PICTURE_TYPE_WMF;
		} else if (fileName.endsWith(".pict")) {
			format = XWPFDocument.PICTURE_TYPE_PICT;
		} else if (fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")) {
			format = XWPFDocument.PICTURE_TYPE_JPEG;
		} else if (fileName.endsWith(".png")) {
			format = XWPFDocument.PICTURE_TYPE_PNG;
		} else if (fileName.endsWith(".dib")) {
			format = XWPFDocument.PICTURE_TYPE_DIB;
		} else if (fileName.endsWith(".gif")) {
			format = XWPFDocument.PICTURE_TYPE_GIF;
		} else if (fileName.endsWith(".tiff")) {
			format = XWPFDocument.PICTURE_TYPE_TIFF;
		} else if (fileName.endsWith(".eps")) {
			format = XWPFDocument.PICTURE_TYPE_EPS;
		} else if (fileName.endsWith(".bmp")) {
			format = XWPFDocument.PICTURE_TYPE_BMP;
		} else if (fileName.endsWith(".wpg")) {
			format = XWPFDocument.PICTURE_TYPE_WPG;
		} else {
			LOGGER.error("Invalid File Format, file=[{}].", fileName);
			throw new RuntimeException("Unsupported picture: " + fileName
					+ ". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg");
		}
		return format;
	}
	
	public static OutputStream replace(String srcPath, String destPath, Map<String, String> map) {
		XWPFDocument document = null;
		OutputStream os = null;
		try {
			document = new XWPFDocument(POIXMLDocument.openPackage(srcPath));
			List<XWPFParagraph> paragraphList = document.getParagraphs();
			
			for (XWPFParagraph paragraph : paragraphList) {
				String s = paragraph.getParagraphText();
				if (StringUtils.isBlank(s)) {
					continue;
				}
				
				for (Entry<String, String> entry : map.entrySet()) {
					String key = entry.getKey();
					String value = entry.getValue();
					List<XWPFRun> runList = paragraph.getRuns();
					for (int i = 0; i < runList.size(); i++) {
						XWPFRun run = runList.get(i);
						String text = run.getText(run.getTextPosition());
						if (StringUtils.isNotBlank(text)) {
							if (text.indexOf(key) > -1) {
								// 参数0表示生成的文字是要从哪一个地方开始放置,设置文字从位置0开始 就可以把原来的文字全部替换掉了
								text = text.replace(key, value);
								run.setText(text, 0);
							}
						}
					}
				}
			}

			// 替换表格中的指定文字
			List<XWPFTable> tableList = document.getTables();
			for (XWPFTable table : tableList) {
				int rcount = table.getNumberOfRows();
				for (int i = 0; i < rcount; i++) {
					XWPFTableRow row = table.getRow(i);
					List<XWPFTableCell> cells = row.getTableCells();
					for (XWPFTableCell cell : cells) {
						String cellText = cell.getText();
						if (StringUtils.isNotBlank(cellText)) {
							continue;
						}
						for (Entry<String, String> entry : map.entrySet()) {
							String key = entry.getKey();
							String value = entry.getValue();
							
							if (cellText.indexOf(key) > -1) {
								cellText = cellText.replace(key, value);
								cell.removeParagraph(0);
								cell.setText(cellText);
							}
						}
					}
				}
			}
			os = new ByteArrayOutputStream();
			document.write(os);
		} catch (Exception e) {
			LOGGER.error("replace docx Exception，msg=[{}].", e.getMessage());
		} finally {
			if (document != null) {
				try {
					document.close();
				} catch (IOException e) {
					// ignore
				}
			}
		}
		return os;
	}
	
	public static void main(String[] args) {
		String docxPath = "c:\\works\\test.docx";
		String[] images = new String[] {"C:\\Users\\yinlei\\Pictures\\B2E7GS9K00AJ0003.jpg", "C:\\Users\\yinlei\\Pictures\\B2E7GQFH00AJ0003.jpg"};
		try {
			FileOutputStream fos = new FileOutputStream("c:\\works\\test2.docx");
			update(docxPath, images, fos);
			fos.flush();
			IOUtils.closeQuietly(fos);
		} catch (IOException e) {
			
		}
		
	}
}
